package com.hccl.controller;

import DM.DialogManager;
import com.hccl.exception.updateException;
import com.hccl.exception.updateFileOperateException;
import com.hccl.service.parser.Parser;
import com.hccl.service.parser.ParserService;
import com.hccl.mongoEntities.ParserParamEntity;
import entities.Reply;
import entities.SLUResult;
import entities.SysAction;
import gate.Annotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.util.*;

import com.hccl.mongoEntities.ResultsEntity;

@RestController
@RequestMapping("/nlp")
public class SLUController {

    private static final Logger logger = LoggerFactory.getLogger(SLUController.class);
    @Autowired
    private ParserService parserService;

    /**
     * description: 理解接口
     *
     * @return 服务响应结果ResultsEntity
     * @Param: url请求参数实体parserParam
     */
    @RequestMapping(value = "/parser", method = RequestMethod.GET)
    @ResponseBody
    public ResultsEntity parser(@Validated ParserParamEntity parserParam) throws Exception {
        ResultsEntity results = new ResultsEntity();
        if (parserParam.getOffline() != null && parserParam.getOffline().equalsIgnoreCase("true")) {
            parserService.dmReset(parserParam);
        }
        String qurey = (parserParam.getKeypad() != null) ? parserParam.getKeypad() : parserParam.getLine();
        if (qurey == null) qurey = "";
        try {
            Map<String, Object> resultMap = parserService.sluParser(parserParam);
            SysAction action = (SysAction) resultMap.get("currentAction");
            SLUResult sluResult = (SLUResult) resultMap.get("currentSLU");
            //ArrayList<SLUResult> sluResults = (ArrayList<SLUResult>) resultMap.get("originSLU");
            String sluResultStr = "";
            String actions_str = "";
            String targets_str = "";
            String algorithm_str = "";
            String rulename_str = "";
            String ruletype_str = "";

            if (sluResult != null) {
                sluResultStr = sluResult.toString();
                ArrayList<String> actions = new ArrayList<String>();
                ArrayList<String> algorithms = new ArrayList<String>();
                ArrayList<String> rulenames = new ArrayList<String>();
                ArrayList<String> ruletypes = new ArrayList<String>();

                String action_str = sluResult.matchedAction;
                actions.add(action_str);
                algorithms.add(sluResult.algorithmType);
                rulenames.add(sluResult.ruleName);
                ruletypes.add(sluResult.ruleType);

                actions_str = actions.toString();
                ArrayList<String> targets = new ArrayList<String>();
                algorithm_str = algorithms.toString();
                rulename_str = rulenames.toString();
                ruletype_str = ruletypes.toString();
                String target_str = sluResult.matchedTarget;
                targets.add(target_str);

                targets_str = targets.toString();
            }
            logger.info("\n" + "===================================================" + "\n"
                    + "query: " + qurey + "\n" + "sluResult: " + sluResultStr + "\n"
                    + "actions: " + actions_str + "\n" + "targets: " + targets_str + "\n"
                    + "algorithm: " + algorithm_str + "\n" + "rulenames: " + rulename_str + "\n"
                    + "ruletypes: " + ruletype_str + "\n"
                    + "===================================================          " + "\n");

            //新增需求，nx_start根据日期返回，月初返回nx_start1,月中返回nx_start2,月末返回nx_start3
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis(System.currentTimeMillis());
            int day = cal.get(Calendar.DATE);
            String content = day < 11 ? "nx_start1" : day < 21 ? "nx_start2" : "nx_start3";
            List<Reply> replies = action.reply;
            for (int i = 0; i < replies.size(); i++) {
                if (replies.get(i).getContent().contains("nx_start")) {
                    replies.get(i).setContent(content);
                }
            }

            results.setReply(replies);
            results.setUserid(parserParam.getUserid());
            results.setAction(action.stateID);
            results.setSlu_Action(action.action);
            results.setSlu_Target(action.target);
            results.setSlu_slot(action.slots);
            results.setParams(action.params);
            results.setInput(qurey);
            results.setFinalSluResult(action.finalSluResult);
            results.setFunction(action.query);
            results.setKeypad(action.keypad);
            if (parserParam.getDebug() != null && parserParam.getDebug().trim().toLowerCase().equals("true")) {
                results.setDebug(sluResult);
                results.setGazetteer((Set<Annotation>) resultMap.get("currentGaz"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (qurey != null)
                System.out.println(qurey);
        }
        return results;
    }

    /**
     * description: 语法语料等配置文件更新接口
     *
     * @return 服务响应结果更新是否成功
     * @Param: null
     */
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Object> update() {
        JSONObject json = new JSONObject();
        String result = "";
        json.put("code", "0");
        try {
            parserService.backupFiles();
            Boolean updateResult = parserService.update();
            parserService.deleteRecoveryFile();
            result = updateResult ? "更新成功" : "更新失败";
            logger.info("更新成功！");
        } catch (updateFileOperateException e) {  //处理文件操作类异常
            json.put("code", "-1");
            result = e.getMessage();
            logger.error("更新失败！请手动恢复lib文件夹，并重启语义理解服务。");
        } catch (updateException e) {             //update逻辑类异常，针对update()
            result = e.getMessage();
            json.put("code", "-1");
            try {
                parserService.recovery();
                logger.error("更新失败！但系统配置自动恢复至更新前状态。");
            } catch (updateFileOperateException e1) {
                result = e1.getMessage();
                logger.error("更新失败！请手动恢复lib文件夹，并重启语义理解服务。");
            }
        }

        json.put("result", result);
        return new ResponseEntity<Object>(json.toString(), HttpStatus.OK);
    }


    /**
     * description: 语法语料等配置文件更新接口
     *
     * @return 服务响应结果更新是否成功
     * @Param: null
     */
    @RequestMapping(value = "/updateProcess", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Object> updateProcess() {
        JSONObject json = new JSONObject();
        String result = "";
        json.put("code", "-1");
        json.put("result", result);
        boolean updateResult = false;
        try {
            updateResult = parserService.updateProcess();
        }catch (Exception e){
            updateResult =false;
        }
        if (updateResult==true){
            json.put("code","0");
            json.put("result","【更新成功】");
        }
        return new ResponseEntity<Object>(json.toString(), HttpStatus.OK);
    }

    /**
     * description: 语料批量测试接口
     *
     * @return 服务响应结果测试是否成功
     * @Param: null
     */
    @RequestMapping(value = "/testCorpus", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Object> testCorpus() {
        JSONObject json = new JSONObject();
        String resultMessage = "语义理解结果文件见testCorpusResult.txt。";
        try {
            parserService.test();
        } catch (Exception e) {
            resultMessage = "测试出错。";
            logger.error("测试出错。");
            e.printStackTrace();
        }
        json.put("code", "0");
        json.put("result", resultMessage);
        return new ResponseEntity<Object>(json.toString(), HttpStatus.OK);
    }


}